Skip to content

Method: checkCondition(Boolean, Double)

1: package de.fhdw.gaming.ipspiel22.vierGewinnt.strategy;
2:
3: import java.util.ArrayList;
4: import java.util.Collections;
5: import java.util.List;
6: import java.util.Objects;
7:
8: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.VGMove;
9: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.AbstractVGMove;
10: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG1ColumnMove;
11: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG2ColumnMove;
12: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG3ColumnMove;
13: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG4ColumnMove;
14: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG5ColumnMove;
15: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG6ColumnMove;
16: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG7ColumnMove;
17: import de.fhdw.gaming.core.domain.GameException;
18: import de.fhdw.gaming.ipspiel22.searchtree.domain.MinMaxGame;
19: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGAnswerEnum;
20: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGBoard;
21: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGField;
22: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGFieldState;
23: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGPlayer;
24: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGPosition;
25: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGState;
26: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.impl.VGBoardImpl;
27:
28: /**
29: * MinMaxViergewinnt.
30: */
31: @SuppressWarnings({ "PMD.GodClass", "PMD.CyclomaticComplexity" })
32: public class MinMaxViergewinnt implements MinMaxGame<VGPlayer, VGState, VGMove> {
33: /**
34: * Current given state.
35: */
36: private final VGState vgState;
37:
38: /**
39: * Current given state.
40: */
41: private final VGBoard inistialBoard;
42:
43: /**
44: * Current given player.
45: */
46: private final VGPlayer player;
47:
48: /**
49: * Playercolour for algorithm.
50: */
51: private Boolean playercolour;
52:
53: /**
54: * Saved Move.
55: */
56: private VGMove savedMove;
57:
58: /**
59: * For creating MinMaxViergewinnt.
60: *
61: * @param state Current given state.
62: * @param player Current given player.
63: */
64: public MinMaxViergewinnt(final VGState state, final VGPlayer player) {
65: this.vgState = state;
66: this.player = player;
67: this.playercolour = player.isUsingRedChips();
68: this.inistialBoard = new VGBoardImpl((VGBoardImpl) state.getBoard());
69: }
70:
71: @Override
72: public double evaluateStateful() {
73: double stateful;
74:
75: final VGFieldState state = playercolour ? VGFieldState.RED : VGFieldState.YELLOW;
76: final VGFieldState otherPlayerState = !playercolour ? VGFieldState.RED : VGFieldState.YELLOW;
77:
78: final List<Double> checkedStates = new ArrayList<>();
79: if (this.playercolour == this.player.isUsingRedChips()) {
80:
81: checkedStates.addAll(twoCombo(vgState.getBoard(), state, 6.0));
82: checkedStates.addAll(threeCombo(vgState.getBoard(), state, 12.0));
83: checkedStates.addAll(fourCombo(vgState.getBoard(), state, 24.0));
84:
85: stateful = Collections.max(checkedStates);
86: stateful += checkMiddle(vgState.getBoard(), playercolour);
87:
88: final List<Double> firstPossibleMoves = new ArrayList<>();
89: firstPossibleMoves.add(ifThreeWithMove(otherPlayerState,
90: !this.player.isUsingRedChips()));
91: firstPossibleMoves.add(ifThreeWithMove(state, this.player.isUsingRedChips()));
92: firstPossibleMoves.add(ifWonWithMove(otherPlayerState,
93: !this.player.isUsingRedChips()));
94: firstPossibleMoves.add(ifWonWithMove(state, this.player.isUsingRedChips()));
95: stateful += Collections.max(firstPossibleMoves);
96:
97: } else {
98: checkedStates.addAll(threeCombo(vgState.getBoard(), state, 5.0));
99: checkedStates.addAll(fourCombo(vgState.getBoard(), state, 20.0));
100:
101: stateful = Collections.max(checkedStates);
102: }
103: return stateful;
104: }
105:
106: @Override
107: public boolean isGameOver() {
108: final List<VGField> allFields = new ArrayList<>();
109: vgState.getBoard().getFields().forEach(allFields::addAll);
110:
111: if (allFields.stream().noneMatch(vgField -> vgField.getState().equals(VGFieldState.EMPTY))) {
112: return true;
113: } else {
114: return checkWinner(vgState.getBoard(), playercolour); // checkWinner(!playercolour);
115: }
116: }
117:
118: @Override
119: public List<VGMove> getPossibleMoves() {
120: final List<VGMove> movesList = new ArrayList<>();
121:
122: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.FIRSTCOLUMN))) {
123: movesList.add(new VG1ColumnMove());
124: }
125: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.SECONDCOLUMN))) {
126: movesList.add(new VG2ColumnMove());
127: }
128: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.THIRDCOLUMN))) {
129: movesList.add(new VG3ColumnMove());
130: }
131: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.FOURTHCOLUMN))) {
132: movesList.add(new VG4ColumnMove());
133: }
134: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.FITFHCOLUMN))) {
135: movesList.add(new VG5ColumnMove());
136: }
137: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.SIXTHCOLUMN))) {
138: movesList.add(new VG6ColumnMove());
139: }
140: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.SEVENTHCOLUMN))) {
141: movesList.add(new VG7ColumnMove());
142: }
143: Collections.shuffle(movesList);
144: return movesList;
145: }
146:
147: @Override
148: public void commitMove(final VGMove move) throws GameException {
149: final VGPlayer playerMove = this.playercolour ? vgState.getRedPlayer() : vgState.getYellowPlayer();
150:
151: move.applyTo(this.vgState, playerMove);
152: this.playercolour = !this.playercolour;
153:
154: this.savedMove = move;
155: }
156:
157: @Override
158: public void rollbackMove(final VGMove move) {
159: if (move instanceof AbstractVGMove) {
160: vgState.getBoard().getFields().get(((AbstractVGMove) move).getColumnInt() - 1);
161:
162: int count = 0;
163: VGField field = vgState.getBoard().getFields().get(((AbstractVGMove) move)
164: .getColumnInt() - 1).get(count);
165: while (!field.getState().equals(VGFieldState.EMPTY) && count < 5) {
166: count += 1;
167: field = vgState.getBoard().getFields().get(((AbstractVGMove) move)
168: .getColumnInt() - 1).get(count);
169: }
170: vgState.getBoard().getFields().get(((AbstractVGMove) move).getColumnInt() - 1)
171: .get(count == 0 ? count : count - 1)
172: .setState(VGFieldState.EMPTY);
173: }
174: this.playercolour = !this.playercolour;
175: }
176:
177: /**
178: * If possible to win with next move.
179: *
180: * @param state
181: * @param playercolor
182: * @return
183: */
184: private double ifWonWithMove(final VGFieldState state, final Boolean playercolor) {
185: final double value = playercolor == player.isUsingRedChips() ? 100.0 : 50.0;
186: return letsWinIfPossible(state, getMoveAsAnswer(this.savedMove),
187: playercolor) ? value : 0;
188: }
189:
190: /**
191: * converts Move to Answer.
192: *
193: * @param move
194: * @return
195: */
196: private VGAnswerEnum getMoveAsAnswer(final VGMove move) {
197: if (move instanceof VG1ColumnMove) {
198: return VGAnswerEnum.FIRSTCOLUMN;
199: } else if (move instanceof VG2ColumnMove) {
200: return VGAnswerEnum.SECONDCOLUMN;
201: } else if (move instanceof VG3ColumnMove) {
202: return VGAnswerEnum.THIRDCOLUMN;
203: } else if (move instanceof VG4ColumnMove) {
204: return VGAnswerEnum.FOURTHCOLUMN;
205: } else if (move instanceof VG5ColumnMove) {
206: return VGAnswerEnum.FITFHCOLUMN;
207: } else if (move instanceof VG6ColumnMove) {
208: return VGAnswerEnum.SIXTHCOLUMN;
209: } else {
210: return VGAnswerEnum.SEVENTHCOLUMN;
211: }
212: }
213:
214: /**
215: * If possible to have three chips in next move.
216: *
217: * @param state
218: * @param playercolor
219: * @return
220: */
221: private double ifThreeWithMove(final VGFieldState state, final boolean playercolor) {
222: final double value = playercolor == player.isUsingRedChips() ? 20.0 : 10.0;
223: return putThreeIfPossible(state, getMoveAsAnswer(this.savedMove)) ? value : 0;
224: }
225:
226: /**
227: * Win if possible.
228: *
229: * @param state
230: * @param column
231: * @param playercolor
232: * @return
233: */
234: private Boolean letsWinIfPossible(final VGFieldState state, final VGAnswerEnum column,
235: final Boolean playercolor) {
236: final VGField field = inistialBoard.getNextFieldInColumn(column);
237: Boolean won = false;
238: if (Objects.nonNull(field)) {
239: field.setState(state);
240: won = checkWinner(inistialBoard, playercolor);
241: field.setState(VGFieldState.EMPTY);
242: }
243: return won;
244: }
245:
246: /**
247: * Three if possible.
248: *
249: * @param state
250: * @param column
251: * @return
252: */
253: private Boolean putThreeIfPossible(final VGFieldState state, final VGAnswerEnum column) {
254: final VGField field = inistialBoard.getNextFieldInColumn(column);
255: Boolean won = false;
256: if (Objects.nonNull(field)) {
257: field.setState(state);
258: won = Collections.max(threeCombo(inistialBoard, state, 20.0)) > 0;
259: field.setState(VGFieldState.EMPTY);
260: }
261: return won;
262: }
263:
264: // -----------------------------------------------------------------------------------------------------
265:
266: /**
267: * Returns boolean, if Player has won.
268: *
269: * @param board
270: * @param usingRedChips The current player.
271: */
272: private boolean checkWinner(final VGBoard board, final Boolean usingRedChips) {
273: final VGFieldState state = usingRedChips ? VGFieldState.RED : VGFieldState.YELLOW;
274: return checkHorizontaleLeftToRight(board, state, state, state, state)
275: || checkVertikaleDownUp(board, state, state, state, state)
276: || checkDiagonaleDownLeftUpRight(board, state, state, state, state)
277: || checkDiagonaleDownRightUpLeftght(board, state, state, state, state);
278: }
279:
280: /**
281: * Checks condition, if true return rating else 0.0.
282: * @param condition
283: * @param rating
284: * @return
285: */
286: private Double checkCondition(final Boolean condition, final Double rating) {
287:• return condition ? rating : 0.0;
288: }
289:
290: /**
291: * Checks if a two combo exists.
292: *
293: * @param board
294: * @param state
295: * @param rating
296: * @return
297: */
298: public List<Double> twoCombo(final VGBoard board, final VGFieldState state,
299: final Double rating) {
300: final List<Double> checkedStates = new ArrayList<>();
301: checkedStates
302: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, VGFieldState.EMPTY, state,
303: VGFieldState.EMPTY, state), rating));
304: checkedStates.add(
305: checkCondition(checkDiagonaleDownRightUpLeftght(board, VGFieldState.EMPTY, state,
306: VGFieldState.EMPTY, state), rating));
307: checkedStates
308: .add(checkCondition(checkHorizontaleLeftToRight(board, VGFieldState.EMPTY, state,
309: VGFieldState.EMPTY, state), rating));
310:
311: checkedStates
312: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, VGFieldState.EMPTY,
313: state, VGFieldState.EMPTY), rating));
314: checkedStates.add(
315: checkCondition(checkDiagonaleDownRightUpLeftght(board, state, VGFieldState.EMPTY,
316: state, VGFieldState.EMPTY), rating));
317: checkedStates
318: .add(checkCondition(checkHorizontaleLeftToRight(board, state, VGFieldState.EMPTY,
319: state, VGFieldState.EMPTY), rating));
320:
321: checkedStates
322: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, state, VGFieldState.EMPTY,
323: VGFieldState.EMPTY), rating));
324: checkedStates.add(
325: checkCondition(checkDiagonaleDownRightUpLeftght(board, state, state, VGFieldState.EMPTY,
326: VGFieldState.EMPTY), rating));
327: checkedStates
328: .add(checkCondition(checkHorizontaleLeftToRight(board, state, state, VGFieldState.EMPTY,
329: VGFieldState.EMPTY), rating));
330:
331: checkedStates
332: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, VGFieldState.EMPTY,
333: VGFieldState.EMPTY, state), rating));
334: checkedStates.add(
335: checkCondition(checkDiagonaleDownRightUpLeftght(board, state, VGFieldState.EMPTY,
336: VGFieldState.EMPTY, state), rating));
337: checkedStates
338: .add(checkCondition(checkHorizontaleLeftToRight(board, state, VGFieldState.EMPTY,
339: VGFieldState.EMPTY, state), rating));
340:
341: checkedStates
342: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, VGFieldState.EMPTY,
343: VGFieldState.EMPTY, state, state), rating));
344: checkedStates.add(
345: checkCondition(checkDiagonaleDownRightUpLeftght(board, VGFieldState.EMPTY,
346: VGFieldState.EMPTY, state, state), rating));
347: checkedStates
348: .add(checkCondition(checkHorizontaleLeftToRight(board, VGFieldState.EMPTY,
349: VGFieldState.EMPTY, state, state), rating));
350:
351: checkedStates
352: .add(checkCondition(checkVertikaleDownUp(board, state, state, VGFieldState.EMPTY,
353: VGFieldState.EMPTY), rating));
354: return checkedStates;
355: }
356:
357: /**
358: * Checks if three Combo exists.
359: *
360: * @param board
361: * @param state
362: * @param rating
363: * @return
364: */
365: public List<Double> threeCombo(final VGBoard board, final VGFieldState state, final Double rating) {
366: // Drei gewinnt
367: final List<Double> checkedStates = new ArrayList<>();
368: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, state,
369: VGFieldState.EMPTY, state), rating));
370: checkedStates
371: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board, state, state,
372: VGFieldState.EMPTY, state), rating));
373: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board, state, state,
374: VGFieldState.EMPTY, state), rating));
375:
376: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board, state,
377: VGFieldState.EMPTY, state, state), rating));
378: checkedStates
379: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board, state,
380: VGFieldState.EMPTY, state, state), rating));
381: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board, state,
382: VGFieldState.EMPTY, state, state), rating));
383:
384: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board,
385: VGFieldState.EMPTY, state, state, state), rating));
386: checkedStates
387: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board,
388: VGFieldState.EMPTY, state, state, state), rating));
389: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board,
390: VGFieldState.EMPTY, state, state, state), rating));
391:
392: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board, state,
393: state, state, VGFieldState.EMPTY), rating));
394: checkedStates.add(checkCondition(checkVertikaleDownUp(board, state, state,
395: state, VGFieldState.EMPTY), rating));
396: checkedStates
397: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board, state,
398: state, state, VGFieldState.EMPTY), rating));
399: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board, state,
400: state, state, VGFieldState.EMPTY), rating));
401: return checkedStates;
402: }
403:
404: /**
405: * If four combo exists.
406: *
407: * @param board
408: * @param state
409: * @param rating
410: * @return
411: */
412: public List<Double> fourCombo(final VGBoard board, final VGFieldState state, final Double rating) {
413: // Vier gewinnt
414: final List<Double> checkedStates = new ArrayList<>();
415: checkedStates.add(checkDiagonaleDownLeftUpRight(board, state, state, state, state) ? rating : 0.0);
416: checkedStates.add(checkVertikaleDownUp(board, state, state, state, state) ? rating : 0.0);
417: checkedStates.add(checkDiagonaleDownRightUpLeftght(board, state, state, state, state) ? rating : 0.0);
418: checkedStates.add(checkHorizontaleLeftToRight(board, state, state, state, state) ? rating : 0.0);
419: return checkedStates;
420: }
421:
422:
423: /**
424: * Extra Points for chips in the middle.
425: *
426: * @param board
427: * @param usingRedChips
428: * @return result
429: */
430: private double checkMiddle(final VGBoard board, final boolean usingRedChips) {
431: double result = 0.0;
432: final VGFieldState state = usingRedChips ? VGFieldState.RED : VGFieldState.YELLOW;
433:
434: result += board.getFields().get(2).stream().filter(field -> field.getState().equals(state))
435: .mapToDouble(field -> {
436: return 2.0;
437: }).sum(); // Dritte Spalte
438: result += board.getFields().get(3).stream().filter(field -> field.getState().equals(state))
439: .mapToDouble(field -> {
440: return 5.0;
441: }).sum(); // Vierte Spalte
442: result += board.getFields().get(4).stream().filter(field -> field.getState().equals(state))
443: .mapToDouble(field -> {
444: return 2.0;
445: }).sum(); // Fünfte Spa 0;
446:
447: return result;
448: }
449:
450: /**
451: * Checks horizontal.
452: *
453: * @param board
454: * @param chip1
455: * @param chip2
456: * @param chip3
457: * @param chip4
458: * @return
459: */
460: private Boolean checkHorizontaleLeftToRight(final VGBoard board, final VGFieldState chip1,
461: final VGFieldState chip2,
462: final VGFieldState chip3, final VGFieldState chip4) {
463: for (int i = 0; i < board.getRows(); i++) {
464: for (int j = 0; j < 4; j++) {
465: if (board.getFieldAt(VGPosition.of(j, i)).getState().equals(chip1)
466: && board.getFieldAt(VGPosition.of(j + 1, i)).getState().equals(chip2)
467: && board.getFieldAt(VGPosition.of(j + 2, i)).getState().equals(chip3)
468: && board.getFieldAt(VGPosition.of(j + 3, i)).getState().equals(chip4)) {
469: return true;
470: }
471: }
472: }
473: return false;
474: }
475:
476: /**
477: * checks vertical.
478: *
479: * @param board
480: * @param chip1
481: * @param chip2
482: * @param chip3
483: * @param chip4
484: * @return
485: */
486: private Boolean checkVertikaleDownUp(final VGBoard board, final VGFieldState chip1, final VGFieldState chip2,
487: final VGFieldState chip3,
488: final VGFieldState chip4) {
489: for (int i = 0; i < board.getColumns(); i++) {
490: for (int j = 0; j < 3; j++) {
491: if (board.getFieldAt(VGPosition.of(i, j)).getState().equals(chip1)
492: && board.getFieldAt(VGPosition.of(i, j + 1)).getState().equals(chip2)
493: && board.getFieldAt(VGPosition.of(i, j + 2)).getState().equals(chip3)
494: && board.getFieldAt(VGPosition.of(i, j + 3)).getState().equals(chip4)) {
495: return true;
496: }
497: }
498: }
499: return false;
500: }
501:
502: /**
503: * checks diagonale down left to up right.
504: *
505: * @param board
506: * @param chip1
507: * @param chip2
508: * @param chip3
509: * @param chip4
510: * @return
511: */
512: private Boolean checkDiagonaleDownLeftUpRight(final VGBoard board, final VGFieldState chip1,
513: final VGFieldState chip2,
514: final VGFieldState chip3, final VGFieldState chip4) {
515: for (int i = 0; i < 3; i++) {
516: for (int j = 0; j < 4; j++) {
517: if (board.getFieldAt(VGPosition.of(j, i)).getState().equals(chip1)
518: && board.getFieldAt(VGPosition.of(j + 1, i + 1)).getState()
519: .equals(chip2)
520: && board.getFieldAt(VGPosition.of(j + 2, i + 2)).getState()
521: .equals(chip3)
522: && board.getFieldAt(VGPosition.of(j + 3, i + 3)).getState()
523: .equals(chip4)) {
524: return true;
525: }
526: }
527: }
528: return false;
529:
530: }
531:
532: /**
533: * checks diagonle down right to up left.
534: *
535: * @param board
536: * @param chip1
537: * @param chip2
538: * @param chip3
539: * @param chip4
540: * @return
541: */
542: private Boolean checkDiagonaleDownRightUpLeftght(final VGBoard board, final VGFieldState chip1,
543: final VGFieldState chip2, final VGFieldState chip3, final VGFieldState chip4) {
544: for (int i = 0; i < 3; i++) {
545: for (int j = 3; j < 7; j++) {
546: if (board.getFieldAt(VGPosition.of(j, i)).getState().equals(chip1)
547: && board.getFieldAt(VGPosition.of(j - 1, i + 1)).getState()
548: .equals(chip2)
549: && board.getFieldAt(VGPosition.of(j - 2, i + 2)).getState()
550: .equals(chip3)
551: && board.getFieldAt(VGPosition.of(j - 3, i + 3)).getState()
552: .equals(chip4)) {
553: return true;
554: }
555: }
556: }
557:
558: return false;
559: }
560:
561: }